feat: runtime CP<->DP mode switching for xLLM workers.#1968
Conversation
1b6a28c to
8ca601c
Compare
…hing.
Follow-on to the runtime CP<->DP mode switching feature. Adds:
1. AutoFlipController — a scheduler-facing controller that watches
traffic stats and issues SwitchMode RPCs, so an instance can flip
layout autonomously instead of relying on an external caller.
2. Heal path — after a switch, if a small tail of in-flight requests
fails to converge (e.g. long-prefill sequences straddling the flip),
a bounded heal window (default 4 rounds) drains them safely without
holding the whole cluster.
3. CP -> DP pending gate — refuses a CP -> DP flip while
the CP side still has queued long-prefill sequences that would be
silently split apart by the DP layout.
4. 7 bvar metrics on `/vars`:
xllm_mode_flip_total
xllm_mode_flip_success_total
xllm_mode_flip_target_cp_total
xllm_mode_flip_target_dp_total
xllm_mode_flip_latency_ms
xllm_mode_flip_heal_rounds
xllm_mode_flip_pending_gate_reject_total
Testing
-------
* Unit: `auto_flip_decide_target_test` (278 lines, covers stat window,
minimum flip interval, target selection, hysteresis).
* E2E: heal path exercised by the same `verify_switch` regression,
which was extended to inject a long prefill straddling the flip;
842 ms average tail drain, 18/18 flips still convergent.
* Soak: 10 min @ 32 procs with periodic auto-flips, HBM stable.
Depends on xLLM-AI#1968 (feat: runtime CP<->DP mode switching).
There was a problem hiding this comment.
please rebase the latest main branch, we have updated docs dir. Besides, plz add zh version docs.
8ca601c to
99fa9f1
Compare
…hing.
Follow-on to the runtime CP<->DP mode switching feature. Adds:
1. AutoFlipController — a scheduler-facing controller that watches
traffic stats and issues SwitchMode RPCs, so an instance can flip
layout autonomously instead of relying on an external caller.
2. Heal path — after a switch, if a small tail of in-flight requests
fails to converge (e.g. long-prefill sequences straddling the flip),
a bounded heal window (default 4 rounds) drains them safely without
holding the whole cluster.
3. CP -> DP pending gate — refuses a CP -> DP flip while
the CP side still has queued long-prefill sequences that would be
silently split apart by the DP layout.
4. 7 bvar metrics on `/vars`:
xllm_mode_flip_total
xllm_mode_flip_success_total
xllm_mode_flip_target_cp_total
xllm_mode_flip_target_dp_total
xllm_mode_flip_latency_ms
xllm_mode_flip_heal_rounds
xllm_mode_flip_pending_gate_reject_total
Testing
-------
* Unit: `auto_flip_decide_target_test` (278 lines, covers stat window,
minimum flip interval, target selection, hysteresis).
* E2E: heal path exercised by the same `verify_switch` regression,
which was extended to inject a long prefill straddling the flip;
842 ms average tail drain, 18/18 flips still convergent.
* Soak: 10 min @ 32 procs with periodic auto-flips, HBM stable.
Depends on xLLM-AI#1968 (feat: runtime CP<->DP mode switching).
|
Thanks for the review, @XuZhang99! Addressed in the latest push:
Regarding the rebase-to-latest-main request: as noted in the PR description, this branch is based on upstream PR2 (#1969) has been rebased on top of the updated PR1 tip and force-pushed. |
99fa9f1 to
4264e13
Compare
|
Update: rebased PR1 onto the current Rebase conflict resolutions (4 files)
Adaptations to upstream refactors (2 files, non-conflicting but still needed)
Docs move + zh version added earlier are still there. Local build validation attempted on 2 self-hosted A3/ARM boxes with the same PR2 (#1969) will be re-based on top of the updated PR1 once this one settles. |
…hing.
Follow-on to the runtime CP<->DP mode switching feature. Adds:
1. AutoFlipController — a scheduler-facing controller that watches
traffic stats and issues SwitchMode RPCs, so an instance can flip
layout autonomously instead of relying on an external caller.
2. Heal path — after a switch, if a small tail of in-flight requests
fails to converge (e.g. long-prefill sequences straddling the flip),
a bounded heal window (default 4 rounds) drains them safely without
holding the whole cluster.
3. CP -> DP pending gate — refuses a CP -> DP flip while
the CP side still has queued long-prefill sequences that would be
silently split apart by the DP layout.
4. 7 bvar metrics on `/vars`:
xllm_mode_flip_total
xllm_mode_flip_success_total
xllm_mode_flip_target_cp_total
xllm_mode_flip_target_dp_total
xllm_mode_flip_latency_ms
xllm_mode_flip_heal_rounds
xllm_mode_flip_pending_gate_reject_total
Testing
-------
* Unit: `auto_flip_decide_target_test` (278 lines, covers stat window,
minimum flip interval, target selection, hysteresis).
* E2E: heal path exercised by the same `verify_switch` regression,
which was extended to inject a long prefill straddling the flip;
842 ms average tail drain, 18/18 flips still convergent.
* Soak: 10 min @ 32 procs with periodic auto-flips, HBM stable.
Depends on xLLM-AI#1968 (feat: runtime CP<->DP mode switching).
Add support for flipping worker layout between CP_PREFILL (cp=N, dp=1) and DP_DECODE (cp=1, dp=N) on a live instance in ~500 ms, without a service restart. Traffic patterns rarely stay in one regime forever; this lets a single deployment adapt across the day rather than being statically sized for either lane. Design ------ * Startup builds BOTH ATB graphs (dual-mode) when `--enable_runtime_cp_dp_switch=true`, so a flip is a graph handle swap, not a rebuild. * Flip flow: scheduler drains in-flight requests -> pause workers -> swap the active `ParallelArgs` (cp/dp) and block-manager pool atomically -> resume. The block-manager pool is guarded by a shared-ptr for lockless reads on the hot path. * Worker-side call sites read the live `parallel_args_.cp_size()` (not the immutable `options_.cp_size()`), so already-scheduled requests observe the new layout after resume. New surfaces ------------ * `mode_switch.proto` + `ModeSwitchService`: RPC surface for flipping, exposed via the xLLM server. * `AutoFlipController` scaffolding for autoscaling callers. * `docs/en/features/runtime_cp_dp_switch.md`: user-facing design doc. Testing ------- * Unit: `dual_parallel_args_test`, `atomic_pool_handle_test`, `lopsided_defer_gate_test`. * E2E on 8*A3: `verify_switch` regression, 18/18 flips stable across 61 model layers; lm_eval CP == DP within tolerance; 10-min soak on 32-proc load did not regress HBM watermark. Related issue: xLLM-AI#1967
4264e13 to
9140c53
Compare
|
@XuZhang99 Thanks for the review! Rebased onto the latest Zh docs are in the branch — New head: |
Description
Add support for runtime CP<->DP mode switching on a live xLLM worker instance in ~500 ms without a service restart.
--enable_runtime_cp_dp_switch=true, so a flip is a graph handle swap rather than a rebuild.ParallelArgs(cp/dp) and block-manager pool atomically → resume.parallel_args_.cp_size()(not the immutableoptions_.cp_size()), so already-scheduled requests observe the new layout after resume.mode_switch.proto+ModeSwitchService, exposed via the xLLM server. Design doc lands underdocs/en/features/runtime_cp_dp_switch.md.--enable_runtime_cp_dp_switch=false(default). When off, worker startup and step paths are byte-identical to today.Follow-on PR (#TBD) adds the AutoFlipController, the heal path, and bvar metrics.
Motivation
Traffic patterns rarely stay in one regime forever — long-context ingest bursts favor CP; concurrent short-request traffic favors DP. Static provisioning per instance forces the operator to overprovision one lane or accept degraded metrics on the other. Runtime CP<->DP mode switching lets an xLLM instance flip layout on demand, so a single deployment can adapt across the day rather than being statically sized for either lane.
Design highlights
dual_parallel_args_is attached to each worker at construction; layer implementations initialize 4 ATB nodes (cp_prefill,cp_decode,dp_prefill,dp_decode) that shareatb_weight_tensors_so there is no weight duplication. Resident cost is ~600 MB / NPU for the extra graph workspace.BlockManagerPoolis guarded by a shared-ptr; the hot read path is lockless, and a flip swaps the handle.HierarchyBlockManagerPoolrebuild only happens at pause time.uses_worker_cp_partition(const ParallelArgs&)overload that reads the liveparallel_args_.cp_size().options_.cp_size()stays frozen at startup; the overload is what callers on the hot path use post-flip.Related Issues
Part of #1967.
Change Type
Pull Request Checklist
PR Title and Commit Messages
<type>: <subject>.Pre-commit Checks
clang-formatwas run against all touched C++ files (verified via--dry-run --Werror, 0 violations).pre-commit run --all-files— not run locally due to environment gap on my dev machine; happy to run whatever the CI does and iterate on any reported issue.Self Review
.agents/skills/code-review/references/custom-code-style.md.mainat commit52eca61a(immediate pre-PR#1938 base). See "Reviewer Notes" below for why notmainHEAD.Build and Test Coverage
dual_parallel_args_test,atomic_pool_handle_test,lopsided_defer_gate_test.python setup.py build test: not run — feature is NPU-only in this PR (no CUDA layer wiring). Behavior on CUDA is unchanged (feature gated off).verify_switchregression on 8*A3 DeepSeek V32 (61 layers), 18/18 flips stable, ~500 ms/flip. lm_eval CP == DP within tolerance. 10-min soak @ 32 procs, HBM watermark stable.Reviewer Notes
52eca61a(immediate pre-PR#1938 base), notmainHEAD, because PR#1938 introduces alaser_attentiondependency that requires a MindIE-SD toolkit not yet in my dev environment. If reviewers prefer, I can rebase onto latestmainonce that toolkit gap is resolved — the feature code itself has no dependency onlaser_attention.xllm/core/layers/npu/npu_deepseek_v32_decoder_layer_impl.cpp(~150 lines added); most of it is symmetric to the existing 2-node init.mode_switch.protois a new file. No changes to existing protos.docs/en/features/runtime_cp_dp_switch.md— happy to iterate here on wording.